home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
video
/
fly8111-.000
/
fly8111-
/
fly8
/
loop.c
< prev
next >
Wrap
C/C++ Source or Header
|
1979-12-31
|
13KB
|
604 lines
/* --------------------------------- loop.c --------------------------------- */
/* This is part of the flight simulator 'fly8'.
* Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
*/
/* This is the main 'busy-loop' of the simulation.
*/
#include "plane.h"
LOCAL_FUNC int NEAR FASTCALL simulate_world (void);
LOCAL_FUNC void NEAR render_bg (OBJECT *pov, int type, int frame,
int hudinfront);
LOCAL_FUNC void NEAR render_fg (OBJECT *pov, int type, int frame,
int hudinfront);
LOCAL_FUNC void NEAR FASTCALL render_picture (void);
LOCAL_FUNC void NEAR FASTCALL show_picture (void);
extern void FAR
active_loop (Ulong t)
{
st.present += t;
st.ObjectTimeout = st.present + TO_OBJECT;
st.PlayerTimeout = st.present + TO_PLAYER;
if (t > 1000L) /* ignore long pauses */
st.interval = REFRESH;
else
st.interval = (int)t;
st.dither = Frand () % 1000;
Tm->Interval (TMR_START, 0L);
if (!(st.flags & SF_PAUSED)) {
if (simulate_world ())
die ();
render_picture (); /* build picture into display list */
}
show_picture (); /* draw display list on screen */
/* Gather stats.
*/
st.misc[0] = (int)Tm->Interval (TMR_STOP, 10000L);
st.misc[2] = (int)STATS_TIME3D;
st.misc[3] = (int)STATS_TIMESIM;
st.misc[4] = (int)STATS_TIMESYNC;
st.misc[5] = (int)STATS_TIMEHDD;
++STATS_FRAMESCOUNT;
STATS_TIMETOTAL += st.misc[0];
STATS_TIMEVIDEO += st.misc[1];
STATS_TTIME3D += STATS_TIME3D;
STATS_TTIMESIM += STATS_TIMESIM;
STATS_TTIMESYNC += STATS_TIMESYNC;
STATS_TTIMEHDD += STATS_TIMEHDD;
STATS_TIME3D = 0L;
STATS_TIMESIM = 0L;
STATS_TIMESYNC = 0L;
STATS_TIMEHDD = 0L;
}
LOCAL_FUNC int NEAR FASTCALL
simulate_world (void)
/*
* Do the global housekeeping. This routine is called repeatedly from the
* main program just before the objects simulation.
*/
{
if (st.quiet >= 2 && IS_PLANE (CC)) { /* engine noise */
#if 0
Snd->Effect (EFF_ENGINE, SND_PARMS, iabs (CC->speed/4));
Snd->Effect (EFF_ENGINE, SND_PARMS, iabs (EE(CC)->thrust/4));
#endif
Snd->Effect (EFF_ENGINE, SND_PARMS, iabs (EE(CC)->power/16));
}
if (objects_dynamics (st.interval))
return (1);
if (land_update (CV))
return (1);
return (0);
}
/* initiate the screen drawing structures.
*/
extern void FAR
screen_start (void)
{
if (st.flags1 & SF_DBUFFERING) {
Gr->SetVisual (st.which_buffer);
Gr->SetActive (1-st.which_buffer);
} else {
if (Gr->SetVisual)
Gr->SetVisual (0);
if (Gr->SetActive)
Gr->SetActive (0);
}
show_fixed (0); /* show */
}
/* empty all screen related structures, drain display lists.
*/
extern void FAR
screen_empty (void)
{
if (st.flags1 & SF_DBUFFERING) {
Gr->SetActive (st.which_buffer);
if (Gr->Clear)
Gr->Clear (CS);
else {
buffers_erase (0);
buffers_erase (1);
}
Gr->SetActive (1-st.which_buffer);
}
if (Gr->Clear)
Gr->Clear (CS);
else {
buffers_erase (0);
buffers_erase (1);
}
buffers_free (0);
buffers_free (1);
if (!Gr->Clear)
show_fixed (1);
}
extern void FAR
double_buffer (int mode)
{
if (!((mode ^ st.flags1) & SF_DBUFFERING))
return;
if (CS->device->npages > 1) {
sim_set ();
screen_empty ();
st.flags1 ^= SF_DBUFFERING;
screen_start ();
sim_reset ();
MsgPrintf (50, "%s buffering",
st.flags1 & SF_DBUFFERING ? "double" : "single");
} else
MsgPrintf (50, "no double buffering");
}
LOCAL_FUNC void NEAR
draw_border (int orgx, int orgy, int sizex, int sizey, int bg, int bo)
{
int xl, xr, yt, yb;
xl = orgx - sizex;
xr = orgx + sizex;
yt = orgy - sizey;
yb = orgy + sizey;
/* draw the border
*/
if (!(st.flags & SF_BLANKER)) {
bo = st.colors[bo];
Gr->MoveTo (xl, yt);
Gr->DrawTo (xr, yt, bo);
Gr->DrawTo (xr, yb, bo);
Gr->DrawTo (xl, yb, bo);
Gr->DrawTo (xl, yt, bo);
}
/* fill in the background
*/
++xl;
--xr;
bg = st.colors[bg];
while (++yt < yb) {
Gr->MoveTo (xl, yt);
Gr->DrawTo (xr, yt, bg);
sys_poll (9);
}
}
LOCAL_FUNC void NEAR FASTCALL
show_border (VIEW *v, int bg, int bo, int dx)
{
int orgx, orgy, sizex, sizey;
orgx = fmul (v->window->orgx, v->screen->sizex) + v->screen->minx;
orgy = fmul (v->window->orgy, v->screen->sizey) + v->screen->miny;
sizex = fmul (v->window->maxx, v->screen->sizex);
sizey = fmul (v->window->maxy, v->screen->sizey);
draw_border (orgx, orgy, sizex, sizey, bg, bo);
if (dx)
draw_border (orgx+dx, orgy, sizex, sizey, bg, bo);
}
LOCAL_FUNC void NEAR FASTCALL
show_borders (int del)
{
int dx, i;
dx = (VIS_STEREOSCOPIC == st.stereo)
? fmul (muldiv(CW->maxx, 2*st.gap+2, st.gap-1), CS->sizex)
: 0;
for (i = 0; i < NHDD; ++i) {
if (st.hdd[i].view.window)
show_border (&st.hdd[i].view, st.hdd[i].BgColor,
del ? st.hdd[i].BgColor : st.hdd[i].BoColor,
0);
}
show_border (CVIEW, CS->BgColor, del ? CS->BgColor : CS->BoColor, dx);
}
LOCAL_FUNC void NEAR FASTCALL
show_fixed_page (int del)
{
show_borders (del);
}
extern void FAR
show_fixed (int del)
{
if (Gr->SetWriteMode)
Gr->SetWriteMode (T_MSET);
if (st.flags1 & SF_DBUFFERING) {
Gr->SetActive (st.which_buffer);
show_fixed_page (del);
Gr->SetActive (1-st.which_buffer);
}
show_fixed_page (del);
}
LOCAL_FUNC void NEAR
render_bg (OBJECT *pov, int type, int frame, int hudinfront)
{
Tm->Interval (TMR_START, 0L);
show_sky (CVIEW, pov);
if (frame && !hudinfront)
show_main (CVIEW, pov, type, 1);
STATS_TIMEHDD += Tm->Interval (TMR_STOP, 10000L);
}
LOCAL_FUNC void NEAR
render_fg (OBJECT *pov, int type, int frame, int hudinfront)
{
Tm->Interval (TMR_START, 0L);
show_main (CVIEW, pov, type, (frame && !hudinfront) ? 0 : 1);
show_inst (CVIEW, CV);
STATS_TIMEHDD += Tm->Interval (TMR_STOP, 10000L);
}
/* st.which_buffer indicated which buffer is now visible.
* bufold is the currently active (invisible) page
* it is drawn, then becomes visible (inactive)
* bufnew is the cuurently visible (inactive) page
* it is erased, then becomes active (invisible)
*/
LOCAL_FUNC void NEAR FASTCALL
show_picture (void)
{
int bufold, bufnew;
Tm->Interval (TMR_START, 0L);
if (st.flags & SF_CLEARED) {
st.flags &= ~SF_CLEARED;
show_fixed (0);
}
if ((st.flags & SF_PAUSED) && (VIS_ALTERNATING != st.stereo))
goto ret;
bufnew = st.which_buffer;
st.which_buffer = (st.which_buffer+1)%NBUFS;
bufold = st.which_buffer;
if (st.flags1 & SF_DBUFFERING) {
Gr->SetActive (bufold); /* access new page */
buffers_show (bufold); /* draw new page */
if (Gr->Clear)
show_fixed_page (0);
Tm->Interval (TMR_START, 0L);
Gr->SetVisual (bufold); /* show new page */
if (VIS_ALTERNATING == st.stereo)
Gr->Shutters (bufold);
STATS_TIMESYNC = Tm->Interval (TMR_STOP, 10000L);
Gr->SetActive (bufnew); /* access old page */
buffers_erase (bufnew); /* erase old page */
buffers_free (bufnew);
} else {
buffers_erase (bufnew); /* erase old page */
buffers_free (bufnew);
if (VIS_ALTERNATING == st.stereo)
Gr->Shutters (bufold);
buffers_show (bufold); /* show new page */
if (Gr->Clear)
show_fixed_page (0);
Tm->Interval (TMR_START, 0L);
if (Gr->SetVisual)
Gr->SetVisual (0); /* show page */
STATS_TIMESYNC = Tm->Interval (TMR_STOP, 10000L);
}
ret:
if (Gr->Flush) {
Tm->Interval (TMR_START, 0L);
Gr->Flush ();
STATS_TIMESYNC = Tm->Interval (TMR_STOP, 10000L);
}
st.misc[1] = (int)(Tm->Interval (TMR_STOP, 10000L) - STATS_TIMESYNC);
}
extern OBJECT * FAR
get_viewer (int type)
{
OBJECT *pov;
for (pov = CO; pov; pov = pov->next) {
if (pov->name == O_VIEWER && pov->misc[0] == type)
break;
}
return (pov);
}
extern void FAR
save_viewport (OBJECT *p)
{
if (!p->viewport) {
if (!NEW (p->viewport))
return;
}
memcpy (p->viewport, CP, sizeof (*p->viewport));
}
extern void FAR
get_viewport (OBJECT *p)
{
if (p->viewport)
memcpy (CP, p->viewport, sizeof (*CP));
else {
CP->flags = 0;
CP->x = 0*FONE; /* viewer at center */
CP->y = 0*FONE;
CP->shift = 0;
CP->eyex = 0;
CP->eyey = 0;
CP->eyez = 0;
CP->rotx = 0;
CP->roty = 0;
CP->rotz = 0;
}
}
/* Render the whole screen. Some data may already be in the display list
* from spurious debug stuff.
*/
LOCAL_FUNC void NEAR FASTCALL
render_picture (void)
{
ANGLE cross; /* stereo cross-eyed angle */
int rev, shift, rotz, hud, scene, hudinfront;
int sscopic_shift;
int frame; /* 0=mono 1=left 2=right */
int type; /* 0=main other=HDD type */
OBJECT *pov;
Ushort save_colors[NCOLORS];
int i;
Ushort color;
st.flags |= SF_MAIN; /* main display */
if (st.flags1 & SF_EXTVIEW) { /* find viewer */
type = st.extview;
hud = (HDT_HUD == type);
scene = scenery (type);
if (scene || hud) {
pov = get_viewer (hud ? HDT_FRONT : type);
if (!pov) {
pov = CV;
type = 0;
}
} else
pov = CV;
} else {
pov = CV;
type = 0;
scene = 1;
}
cross = 0; /*ASIN (fdiv (st.paralax, st.focus));*/
if (st.stereo) {
rev = st.flags1 & SF_STEREOREV;
if (!scene)
hudinfront = 1;
else
hudinfront = st.flags1 & SF_HUDINFRONT;
if (VIS_ALTERNATING == st.stereo && st.which_buffer)
rev = !rev;
if (rev) {
shift = -st.paralax; /* transverse: right eye */
rotz = -cross;
} else {
shift = st.paralax; /* parallel: left eye */
rotz = cross;
}
CP->shift -= shift; /* left eye */
CP->rotz += rotz;
} else {
shift = rotz = 0; /* avoid compiler warning */
hudinfront = 0;
}
if (VIS_REDBLUE == st.stereo) {
memcpy (save_colors, st.colors, sizeof (st.colors));
gr_mode (T_MOR);
} else
gr_mode (T_MSET);
/* First we show the left eye view. This is also used to show the single view
* (mono or alternating stereo).
*/
frame = VIS_REDBLUE == st.stereo ? 1 : 0; /* mono/left frame */
if (frame) {
color = save_colors[ST_SLEFT];
for (i = 0; i < rangeof (st.colors); ++i)
st.colors[i] = color;
}
if (scene) {
render_bg (pov, type, frame, hudinfront);
objects_show (0, CVIEW, pov, frame, 0, 0);
}
if (st.stereo && hudinfront) {
CP->shift += shift; /* back to center */
CP->rotz -= rotz;
}
if (VIS_REDBLUE != st.stereo)
render_fg (pov, type, frame, hudinfront);
if (st.stereo && !hudinfront) {
CP->shift += shift; /* back to center */
CP->rotz -= rotz;
}
/* Second we show the right eye view (for non-alternating stereo).
*/
if (st.stereo && VIS_ALTERNATING != st.stereo) {
if (VIS_STEREOSCOPIC == st.stereo) {
sscopic_shift = muldiv (CW->maxx, 2*st.gap+2, st.gap-1);
CW->orgx += sscopic_shift;
}
CP->shift += shift; /* right eye */
CP->rotz -= rotz;
frame = VIS_REDBLUE == st.stereo ? 2 : 0; /* right frame */
if (frame) {
color = save_colors[ST_SRIGHT];
for (i = 0; i < rangeof (st.colors); ++i)
st.colors[i] = color;
}
if (scene) {
render_bg (pov, type, frame, hudinfront);
objects_show (0, CVIEW, pov, frame, 0, 0);
}
if (hudinfront) {
CP->shift -= shift; /* back to center */
CP->rotz += rotz;
if (VIS_REDBLUE == st.stereo) {
color = save_colors[ST_SBOTH];
for (i = 0; i < rangeof (st.colors); ++i)
st.colors[i] = color;
}
}
render_fg (pov, type, frame, hudinfront);
if (!hudinfront) {
CP->shift -= shift; /* back to center */
CP->rotz += rotz;
}
if (VIS_STEREOSCOPIC == st.stereo)
CW->orgx -= sscopic_shift;
}
buffer_close ();
st.bufs[1-st.which_buffer] = st.buf[HEAD];
st.buf[HEAD] = st.buf[TAIL] = 0;
st.flags &= ~SF_MAIN; /* secondary displays */
if (VIS_REDBLUE == st.stereo) {
color = save_colors[ST_SBOTH];
for (i = 0; i < rangeof (st.colors); ++i)
st.colors[i] = color;
}
show_hdd ();
if (VIS_REDBLUE == st.stereo)
memcpy (st.colors, save_colors, sizeof (st.colors));
STATS_DISPLAYLISTSIZE = buffers_size (1-st.which_buffer);
}
static BUFFER *pause_buf = NULL;
extern void FAR
pause_set (Ushort mode)
{
int orgx, orgy, sizex, sizey;
BUFFER *save_buf[2] = {NULL, NULL};
short save_avail;
if (!((mode ^ st.flags) & SF_PAUSED))
return;
if ((mode & SF_PAUSED) && (st.network & NET_ON)) {
MsgEPrintf (30, "cannot pause on net");
return;
}
if (!(st.flags & SF_PAUSEMSG)) {
st.flags = (st.flags & ~SF_PAUSED) | mode;
return;
}
sim_set (); /* we want immediate response */
/* Get 2D display area parameters.
*/
get_area (CVIEW, &orgx, &orgy, &sizex, &sizey);
if (mode & SF_PAUSED) {
/* save current buf
*/
save_buf[HEAD] = st.buf[HEAD];
save_buf[TAIL] = st.buf[TAIL];
save_avail = st.buf_avail;
buffer_close ();
st.buf[HEAD] = st.buf[TAIL] = 0;
/* create the 'Paused' buf
*/
gr_mode (T_MXOR);
stroke_str (orgx - sizex + 2, orgy - sizey + 2 + st.StFontSize,
"Paused", st.StFontSize, ST_INFO);
/* save it
*/
buffer_close ();
pause_buf = st.buf[HEAD];
/* restore original buf
*/
st.buf[HEAD] = save_buf[HEAD];
st.buf[TAIL] = save_buf[TAIL];
st.buf_p = st.buf[TAIL] ? st.buf[TAIL]->p : NULL;
st.buf_avail = save_avail;
/* show the 'Paused' buf
*/
if (st.flags1 & SF_DBUFFERING) {
Gr->SetActive (st.which_buffer);
buffer_show (pause_buf);
Gr->SetActive (1-st.which_buffer);
}
buffer_show (pause_buf);
st.flags |= SF_PAUSED;
} else {
st.flags &= ~SF_PAUSED;
/* erase the 'Paused' buf, then free it
*/
if (st.flags1 & SF_DBUFFERING) {
Gr->SetActive (st.which_buffer);
buffer_show (pause_buf);
Gr->SetActive (1-st.which_buffer);
}
buffer_show (pause_buf);
buffer_free (pause_buf);
}
sim_reset ();
}